#pragma once
#include "base/function.h"
#include "util/mutex.h"
#include "base/config.h"
#include "net/buffer_reader.h"

#include <sys/uio.h>

namespace net_tools
{
  class Tcpserver;
  class Tcpclient;
  class Eventloop;

  namespace base
  {
    class Channel;
    class Base_buffer;
    class Memorypool;
  } // namespace base

  namespace net
  {
    class Connect;

    class Buffer
    {
      friend class Connect;
      friend class Connectpool;
      friend class Buffer_reader;
      friend class net_tools::Tcpserver;
      friend class net_tools::Tcpclient;

    public:
      Buffer(net_tools::Eventloop *eventloop, Connect *connect);
      ~Buffer(){};
      void Init_channel(net_tools::base::Channel *channel);

      // Connect 接口 用户调用
      // buffer_reader
      Buffer_reader *Read();

      int Read(void *buf, uint32_t max_size);
      // 当套结字关闭的时候返回false 其余则true
      bool Write(void *buf, uint32_t len);
      // 零拷贝接口 未实现
      bool Write(net_tools::base::Base_buffer *base_buffer);
      // 用户接口
      void Close();
      // 用户接口
      void Close_right_now();
      // 用户接口 返回这个包有多大
      uint32_t Peak();

      void Append(void *buf, uint32_t len);

      void Send();

      // 被最顶层类设置 如TCPSERVER
      // 当可以供connect读时调用
      void Set_able_read_callback(connect_func cb);
      // 当套结字被关闭调用的
      void Set_able_close_callback(connect_func cb);
      // 当用户关闭套结字时
      void Set_able_user_close_callback(connect_func cb);

      void Send_heart_beat();

    private:
      // 创建一个预留的长度头
      void Creat_len_head();
      // 将长度设置进去
      void Set_len_head();

      // 修改write_index 满则换区
      void Recv(uint32_t len);
      void Clean_buffer();

      net_tools::base::Base_buffer *Get_new_buf(int size);
      // 查看head_recv_buf是否读完且换到正确的区
      void Read_buf_clear();
      // 从socket中读出 不修改index
      int Read_from_fd(iovec *iovector);
      int Write_in_fd();
      void Analyze_head();
      int Build_head(uint32_t len);

      // 清理 发送接收缓冲区
      //由epoll调用
      void Write_able_callback();
      //由epoll调用
      void Read_able_callback();
      //由epoll调用
      void Close_callback();
      void User_want_close();

      static net_tools::base::Memorypool *mempool_;
      net_tools::Eventloop *eventloop_;
      Connect *connect_;
      net_tools::base::Channel *channel_;
      int fd_;

      connect_func read_callback_;
      connect_func close_callback_;
      connect_func user_want_close_callback_;

      // 只运行在单个线程 如果多线程则使用std::atmoic
      volatile bool send_all_;
      volatile bool user_want_close_;
      volatile bool still_have_;

      //剩余的长度 0为未收到新的包
      uint32_t recv_head_len_;
      uint32_t residue_len_;
      int last_time_head_len_data_len_;

      //send_buf是最初的buf
      net_tools::base::Base_buffer *head_send_buf_;
      net_tools::base::Base_buffer *head_recv_buf_;
      net_tools::base::Base_buffer *now_send_buf_;
      net_tools::base::Base_buffer *now_recv_buf_;

      static __thread Buffer_reader *buffer_reader_;
    };

  } // namespace net
} // namespace net_tools